import { IBaseBehavior } from "../base/IBaseBehavior";
import { BTContext } from "../BTContext";
import { BT_State, BT_Type } from "../BTDefine";

export abstract class BaseBehavior implements IBaseBehavior {
    protected _context: BTContext = null;

    /** 节点类型 */
    protected _type: number = BT_Type.TYPE_TASK;

    /** 当前节点执行状态 */
    protected _state: number = BT_State.NONE;

    /** 预处理状态 */
    protected _cacheState: number = null;   // 预处理状态

    /** tick计数 */
    protected _tick = 0;

    /** 是否执行 */
    protected _isRunning = false;

    public setContext(value) {
        this._context = value;
    }

    public getContext() {
        return this._context;
    }

    public getState(): number {
        return this._state;
    }

    public getType(): number {
        return this._type;
    }

    public setResult(state: number) {
        this._cacheState = state;
    }

    public isRunning() {
        return this._isRunning;
    }

    /**
     * tick中，进入节点、执行节点、退出节点，返回节点执行结果
     * @param dt 
     * @returns 返回当前执行状态
     */
    public tick(dt: number): number {
        if (this.getState() !== BT_State.NONE && this.getState() !== BT_State.RUNNING) {
            return this._state
        }

        this._tick++;

        if (!this._isRunning) {
            this.enter();
        }

        this.run(dt);

        if (this.getState() === BT_State.SUCCESS || this.getState() === BT_State.FAILURE || this.getState() === BT_State.ABORT || this.getState() === BT_State.ERROR) {
            this.exit();
        }

        return this._state;
    }

    /**
     * 中断节点
     * @returns 返回中断状态
     */
    public abort(): number {
        if (this._isRunning) {
            this.exit();
        }

        this._state = BT_State.ABORT;

        return this._state;
    }

    public reset() {
        this._state = BT_State.NONE;
        this._isRunning = false;
        this._tick = 0;
    }


    /**
     * 需实现：进入节点时执行
     */
    public abstract onEnter(): void;

    /**
     * 需实现：退出节点时执行
     */
    public abstract onExit(): void;

    /**
     * 需实现：节点执行过程
     */
    public abstract onProcess(dt: number): void;


    private run(dt: number) {
        this._state = BT_State.RUNNING;

        this.onProcess(dt);

        if (this._cacheState) {
            this._state = this._cacheState;
            this._cacheState = null;
        }
    }

    private enter() {
        this._tick = 0;
        this._isRunning = true;

        this._context.enterBehavior(this);
        this.onEnter();
    }

    private exit() {
        this._isRunning = false;

        this.onExit();
        this._context.exitBehavior(this);
    }

}